#include "hx711.h"
#include "stm32f10x.h"
#include "board.h"
#include <stdio.h>

void HX711_Init(void)
{
		/*定义一个HX711_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef GPIO_InitStructure;

		/*开启相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
		/*选择要控制的GPIO引脚*/

		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
		GPIO_Init(GPIOB, &GPIO_InitStructure);
	
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;	
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   

		GPIO_Init(GPIOB, &GPIO_InitStructure);	

}
	
unsigned long HX711_GetData(void)
{
		unsigned long Count;
		unsigned char i;
		HX711_SCK_L;
	  	//rt_thread_delay(1);
		Count=0;
		while(HX711_DT);
		for (i=0;i<24;i++)
	 	{
			HX711_SCK_H;
			//rt_thread_delay(1);
			Count=Count<<1;
			HX711_SCK_L;
			//rt_thread_delay(1);
			if(HX711_DT) Count++;
		}
		HX711_SCK_H;
		//rt_thread_delay(1);
		Count=Count^0x800000;//最高位取反，其他位不变
	                      //在HX71芯片中，count是一个32位的有符号整数，用于存储称重传感器的读数。
	                      //当count的最高位为1时，表示读数为负数，而HX711芯片不支持负数的读数。
	                      //因此，为了将负数转换为正数，需要将count的最高位取反，即将count与0x800000进行异或操作。
                          //具体来说，0x800000的二进制表示为100000000000000000000000，与count进行异或操作后，
	                      //可以将count的最高位从1变为0，从而得到对应的正数读数。
		HX711_SCK_L;
		//rt_thread_delay(1);
		// rt_kprintf("Count out : %d\r\n", Count);
		return(Count);
}

// 滑动平均滤波函数
int32_t sliding_average_filter(int32_t new_value) 
{
    static int32_t sum = 0;
    // 减去最早的值
    sum -= weight_filter_buffer[filter_index];
    // 加入新的值
    weight_filter_buffer[filter_index] = new_value;
    sum += new_value;
    // 更新索引
    filter_index = (filter_index + 1) % FILTER_WINDOW_SIZE;
    // 返回平均值
    return sum / FILTER_WINDOW_SIZE;
}

// 分段线性映射结构体
typedef struct {
    int32_t input;       // 输入值（滤波后的HX711读数）
    float output;        // 对应的输出重量值(g)
} LinearSegment;

// 分段线性映射表（根据实际校准数据填写）
// 需按照input从小到大的顺序排列
LinearSegment weight_map[] = {
    {8835500, -1.0},          
    {8493860, 100.0},  
    // {4000000, 100.0},  
    // {6000000, 150.0},  
    // {8000000, 200.0}   
};

// 计算映射表长度
#define MAP_LENGTH (sizeof(weight_map) / sizeof(weight_map[0]))

// 分段线性映射函数
float linear_segment_map(int32_t filtered_value) {
    float calculated_weight;
	// 查找所属分段
	int i;
	for (i = 0; i < MAP_LENGTH - 1; i++) {
		if (filtered_value >= weight_map[i].input && 
			filtered_value <= weight_map[i + 1].input) {
			// 计算线性插值
			float ratio = (float)(filtered_value - weight_map[i].input) / 
							(weight_map[i + 1].input - weight_map[i].input);
			calculated_weight = weight_map[i].output + 
					ratio * (weight_map[i + 1].output - weight_map[i].output);
			break;
		}
	}
    
    // 符号处理：正数直接返回，负数返回相反数
    return (calculated_weight >= 0) ? calculated_weight : -calculated_weight;
}

